const cron = require('node-cron');
const moment = require("moment-timezone");

/**
 * 增强的统计定时任务调度器
 * 支持基础统计和转正率统计分离
 */
class EnhancedCronJobScheduler {
    /**
     * 
     * @param {AppleSubscriptionStatsService} statsService 统计业务实例 
     * @param {Array<string>} packages 需要统计的包名数组
     */
    constructor(statsService, packages = []) {
        this.statsService = statsService;
        this.packages = packages;
        this.jobs = new Map();
    }

    /** 启动每日基础统计任务（每天凌晨0点执行昨天的基础数据） */
    startDailyBasicStatsJob() {
        const job = cron.schedule('10 0 * * *', async () => {
            console.log('开始执行每日基础统计任务:', new Date().toISOString());
            for (const pk of this.packages) {
                try {
                    await this.statsService.executeDailyBasicStats(pk);
                    console.log(`完成包 ${pk} 的每日基础统计`);
                } catch (error) {
                    console.error(`包 ${pk} 的每日基础统计失败:`, error);
                }
            }
            console.log('每日基础统计任务完成:', new Date().toISOString());
        }, {
            scheduled: false,
            timezone: "Asia/Shanghai"
        });

        this.jobs.set('dailyBasicStats', job);
        job.start();
        console.log('每日基础统计定时任务已启动（每天0点执行）');
    }

    /** 启动转正率统计任务（每天凌晨1点执行，统计已过试用期的数据） */
    startConversionRateStatsJob() {
        const job = cron.schedule('0 1 * * *', async () => {
            const nowBJ = moment.tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss");
            console.log(`开始执行转正率统计任务: ${nowBJ} (北京时间)`);

            for (const pk of this.packages) {
                try {
                    // 不传日期，让服务自动计算应该统计哪个试用开始日期
                    await this.statsService.executeConversionRateStats(pk);
                    console.log(`完成包 ${pk} 的转正率统计`);
                } catch (error) {
                    console.error(`包 ${pk} 的转正率统计失败:`, error);
                }
            }

            const endBJ = moment.tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm:ss");
            console.log(`转正率统计任务完成: ${endBJ} (北京时间)`);
        }, {
            scheduled: false,
            timezone: "Asia/Shanghai"
        });

        this.jobs.set('conversionRateStats', job);
        job.start();
        console.log('转正率统计定时任务已启动（每天1点执行）');
    }

    /** 启动完整的定时任务（基础统计 + 转正率统计） */
    startAllJobs() {
        this.startDailyBasicStatsJob();
        this.startConversionRateStatsJob();
        console.log('所有定时任务已启动');
    }

    /** 手动执行基础统计 */
    async executeManualBasicStats(pk, date = null) {
        try {
            console.log(`手动执行基础统计任务: ${pk}, 日期: ${date || '昨天'}`);
            await this.statsService.executeDailyBasicStats(pk, date);
            console.log(`手动基础统计任务完成: ${pk}`);
            return { success: true, message: '基础统计任务执行成功' };
        } catch (error) {
            console.error(`手动基础统计任务失败: ${pk}`, error);
            return { success: false, message: error.message };
        }
    }

    /** 手动执行转正率统计 */
    async executeManualConversionStats(pk, trialStartDate = null) {
        try {
            console.log(`手动执行转正率统计任务: ${pk}, 试用开始日期: ${trialStartDate || '自动计算'}`);
            await this.statsService.executeConversionRateStats(pk, trialStartDate);
            console.log(`手动转正率统计任务完成: ${pk}`);
            return { success: true, message: '转正率统计任务执行成功' };
        } catch (error) {
            console.error(`手动转正率统计任务失败: ${pk}`, error);
            return { success: false, message: error.message };
        }
    }

    /** 批量执行历史基础数据统计 */
    async executeHistoricalBasicStats(pk, startDate, endDate) {
        try {
            console.log(`开始执行历史基础数据统计: ${pk}, ${startDate} 到 ${endDate}`);
            await this.statsService.executeHistoricalBasicStats(pk, startDate, endDate);
            console.log(`历史基础数据统计完成: ${pk}`);
            return { success: true, message: '历史基础数据统计完成' };
        } catch (error) {
            console.error(`历史基础数据统计失败: ${pk}`, error);
            return { success: false, message: error.message };
        }
    }

    /** 批量执行历史转正率统计 */
    async executeHistoricalConversionStats(pk, startDate, endDate) {
        try {
            console.log(`开始执行历史转正率统计: ${pk}, ${startDate} 到 ${endDate}`);
            await this.statsService.executeHistoricalConversionStats(pk, startDate, endDate);
            console.log(`历史转正率统计完成: ${pk}`);
            return { success: true, message: '历史转正率统计完成' };
        } catch (error) {
            console.error(`历史转正率统计失败: ${pk}`, error);
            return { success: false, message: error.message };
        }
    }

    /** 
     * 一键补全历史数据（先跑基础统计，再跑转正率统计）
     * @param {string} pk 包名
     * @param {string} startDate 开始日期
     * @param {string} endDate 结束日期
     */

    async executeCompleteHistoricalStats(pk, startDate, endDate) {
        try {
            console.log(`开始完整历史数据统计: ${pk}, ${startDate} 到 ${endDate}`);

            // 1. 先执行基础统计
            console.log('第一步：执行历史基础数据统计...');
            await this.statsService.executeHistoricalBasicStats(pk, startDate, endDate);

            // 2. 再执行转正率统计
            console.log('第二步：执行历史转正率统计...');
            await this.statsService.executeHistoricalConversionStats(pk, startDate, endDate);

            console.log(`完整历史数据统计完成: ${pk}`);
            return { success: true, message: '完整历史数据统计完成' };
        } catch (error) {
            console.error(`完整历史数据统计失败: ${pk}`, error);
            return { success: false, message: error.message };
        }
    }

    /** 动态添加包名到定时队列 */
    addPackage(pk) {
        if (!this.packages.includes(pk)) {
            this.packages.push(pk);
            console.log(`已添加包到定时任务: ${pk}`);
        }
    }

    /** 动态移除包名 */
    removePackage(pk) {
        const index = this.packages.indexOf(pk);
        if (index > -1) {
            this.packages.splice(index, 1);
            console.log(`已从定时任务移除包: ${pk}`);
        }
    }

    /** 停止指定的定时任务 */
    stopJob(jobName) {
        const job = this.jobs.get(jobName);
        if (job) {
            job.stop();
            console.log(`定时任务 ${jobName} 已停止`);
            return true;
        }
        return false;
    }

    /** 启动指定的定时任务 */
    startJob(jobName) {
        const job = this.jobs.get(jobName);
        if (job) {
            job.start();
            console.log(`定时任务 ${jobName} 已启动`);
            return true;
        }
        return false;
    }

    /** 停止所有定时任务 */
    stopAllJobs() {
        this.jobs.forEach((job, name) => {
            job.stop();
            console.log(`定时任务 ${name} 已停止`);
        });
    }

    /** 查询任务状态 */
    getJobStatus() {
        const status = {};
        this.jobs.forEach((job, name) => {
            status[name] = {
                running: job.running,
                scheduled: job.scheduled
            };
        });
        return {
            jobs: status,
            packages: this.packages,
            description: {
                dailyBasicStats: '每日基础统计（0点执行昨天数据）',
                conversionRateStats: '转正率统计（1点执行已过试用期数据）'
            }
        };
    }

    /** 
     * 获取建议的转正率统计日期范围
     * @param {number} maxTrialDays 最大试用天数，默认10天
     */
    getConversionStatsDateRange(maxTrialDays = 10) {
        const today = new Date();
        const endDate = new Date(today);
        endDate.setDate(endDate.getDate() - maxTrialDays - 1); // 往前推最大试用天数+1天

        const startDate = new Date(endDate);
        startDate.setDate(startDate.getDate() - 30); // 往前推30天作为起始范围

        return {
            startDate: startDate.toISOString().split('T')[0],
            endDate: endDate.toISOString().split('T')[0],
            description: `建议统计 ${startDate.toISOString().split('T')[0]} 到 ${endDate.toISOString().split('T')[0]} 的转正率数据`
        };
    }

    // 兼容性方法
    async executeManualStats(pk, date = null) {
        console.log('注意：executeManualStats 已分离为基础统计和转正率统计，建议使用对应的专门方法');
        return await this.executeManualBasicStats(pk, date);
    }

    async executeHistoricalStats(pk, startDate, endDate) {
        console.log('注意：executeHistoricalStats 已分离，建议使用 executeCompleteHistoricalStats 或分别调用基础统计和转正率统计方法');
        return await this.executeCompleteHistoricalStats(pk, startDate, endDate);
    }
}

module.exports = EnhancedCronJobScheduler;